package com.farm.shiro.filter;

import com.farm.common.util.SpringContextUtils;
import com.farm.shiro.service.impl.PermissionService;
import lombok.extern.log4j.Log4j2;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.PathMatchingFilter;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * TalentPathMatchingFilter
 *
 * @author ctidy
 * @since 2021/1/7
 */
@Log4j2
public class MyPathMatchingFilter extends PathMatchingFilter {
    private final PermissionService service = SpringContextUtils.getBean(PermissionService.class);

    @Override
    protected boolean onPreHandle(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {
        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        HttpServletResponse httpServletResponse = (HttpServletResponse) response;

        if (HttpMethod.OPTIONS.toString().equals(httpServletRequest.getMethod())) {
            httpServletResponse.setStatus(HttpStatus.NO_CONTENT.value());
            return true;
        }

        String requestAPI = getPathWithinApplication(request);
        Subject subject = SecurityUtils.getSubject();
        String username = subject.getPrincipal().toString();
        if (!subject.isAuthenticated()) {
            log.info(String.format("未认证用户 %s 尝试访问受限接口 %s, 但被系统拦截", username, requestAPI));
            return false;
        }

        // 判断访问接口是否需要鉴权 (数据库权限表中有无收录)
        if (!service.needFilter(requestAPI)) {
            return true;
        }

        // 判断当前用户是否有相应权限
        if (service.canAccessByAccount(requestAPI, username)) {
            log.trace(String.format("用户 %s 访问了受限接口 %s", username, requestAPI));
            return true;
        }
        log.warn(String.format("用户 %s 尝试无权访问受限接口 %s, 但被系统拦截", username, requestAPI));
        return false;
    }
}
